package com.example.socket.filter.session;

import com.example.socket.core.Request;
import com.example.socket.core.Session;
import com.example.socket.handler.Dispatcher;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Proxy;
import java.util.concurrent.ConcurrentHashMap;

/**
 * @author frank
 * 发送代理工厂
 */
public class PushProxyFactory {
    /** 动态代理处理器 */
    private InvocationHandler invoker;
    private Dispatcher dispatcher;
    private SessionManager manager;

    /** 代理实例缓存 */
    private ConcurrentHashMap<Class<?>, Object> caches = new ConcurrentHashMap<>();

    /** 需要发送的SESSION */
    private ThreadLocal<Session[]> sessions = new ThreadLocal<>();

    public PushProxyFactory(SessionManager manager, Dispatcher dispatcher) {
        this.dispatcher = dispatcher;
        this.manager = manager;
        this.invoker = new PushProxyInvoker<>(this);
    }

    /**
     * 设置发送SESSION
     */
    void setSessions(Session[] sessions) {
        this.sessions.set(sessions);
    }

    /**
     * 发送请求消息
     * @param request
     */
    public void send(Request<Object> request) {
        Session[] sessions = this.sessions.get();
        manager.send(request, sessions);
    }

    /**
     * 获取代理实例
     * @param clz
     * @param sessions
     * @return
     */
    @SuppressWarnings("unchecked")
    public <T> T getProxy(Class<T> clz, Session... sessions) {
        // 设置发送SESSION
        setSessions(sessions);
        // 先从缓存获取
        T obj = (T) caches.get(clz);
        if (obj == null) {
            // 构建新代理并放置到缓存
            obj = (T) Proxy.newProxyInstance(clz.getClassLoader(), new Class[]{clz}, invoker);
            T prev = (T) caches.putIfAbsent(clz, obj);
            obj = prev != null ? prev : obj;
            dispatcher.registerInterface(clz);
        }
        // 注册接口
        return obj;
    }

}
